using System;
using Sce.PlayStation.Core;

namespace Nyanimals
{
    public abstract class CBaseFood : CMovingObject
    {
        protected int   biteCount;    // number of total bites
        protected int   biteTaken;    // number of bites taken
        protected float foodPotency; // base value added each bite
        protected bool  bHeld;
        protected bool  bClaimed;
        
        CFloatLimiter foodScale; // scale representing remaining food.
        
        CBaseObject objectHoldingMe;
        CollisionSphere boundingSphere;
        
        public CBaseFood()
        {
            biteCount = 0;
            foodPotency = 10.0f;
            foodScale = new CFloatLimiter(0.1f, 1.0f, 1.0f);
            boundingSphere = new CollisionSphere(Vector3.Zero, 1.0f);
        }
        
        public override void Init()
        {
        }
        
        public override void Shutdown()
        {
#if SHOWCOLLISION
            CContextManager.Instance.RemoveContext(boundingSphere.Context);
#endif
        }
        
         public override Vector3 Position
         {
            get 
            {
                position = WorldMatrix.AxisW;
                return position;
            }
            set 
            {
                Matrix4 tempWorld = context.WorldMatrix;
                Pivot = boundingSphere.Position = position = tempWorld.AxisW = value;
                Context.WorldMatrix = tempWorld;
            }
         }
        
        public bool CanBite()
        {
            return biteTaken < biteCount;
        }
        
        public bool Held
        {
            get { return bHeld;}
        }
        public bool Claim
        {
            get { return bClaimed;}
            set { bClaimed = value;}
        }
        
        public CollisionSphere BoundingSphere
        {
            get { return boundingSphere;}
        }
        
        public CBaseObject ObjectHolding
        {
            get { return objectHoldingMe;}
            set 
            {
                objectHoldingMe = value;
                if(objectHoldingMe == null)
                {
                    bHeld = false;
                }
                else
                {
                    bHeld = true;
                }
            }
        }
        public virtual bool Bite (CNyanimal nyan)
        {
            // make sure we can bite
            int biteDifference = biteCount - biteTaken;
            bool ret = true;
            if(biteDifference <= 0)
            {
                Console.WriteLine("Nothing Left to Byte");
                ret = false;
            }
            biteTaken++;
            
            // calculate a new scale for the object
            float biteLamda = 1.0f - ((float)biteTaken / (float)biteCount);
            float newValue = CMath.Interpolate(foodScale.Min, foodScale.Max, biteLamda);
            foodScale.Value = newValue;
            
            return ret;
        }
        protected float CalculateStatGain()
        {
            // TODO: tweak this
            // value = potency + potency * remaining food percent
            float foodScaleLamda = foodScale.Max - foodScale.Min;
            foodScaleLamda = (foodScale.Value - foodScale.Min) / foodScaleLamda;
            
            float returnValue = foodPotency + (foodPotency * foodScaleLamda);           
            
            return returnValue;
        }
        
        public override ObjectTypes Type
        {
            get { return ObjectTypes.Food_Object;}
        }
        public virtual FoodTypes FoodType
        {
            get { return FoodTypes.Base_Food;}
        }

        public override void Update (float deltaTime)
        {
            // ensure to keep the collision the same radius as the actual context
            float v = foodScale.Value;
            float r = boundingSphere.Radius;
            if(foodScale.Value != boundingSphere.Radius)
            {
                ScaleAll = boundingSphere.Radius = foodScale.Value;
            }
            
            if(Held)
            {
                CMovingObject obj = (CMovingObject)objectHoldingMe;
                
                // TODO: attach to a joint
                Matrix4 objWorld = obj.WorldMatrix;
                objWorld.AxisW = Vector3.Zero;
                
                Pivot = obj.Position + (objWorld.AxisZ * 1) + (objWorld.AxisY * 1);
                localMatrix = objWorld;      
            }
            else
            {
                // force the Y to be above the ground so it visibly looks like its on the ground
                Vector3 tempPos = Pivot;
                tempPos.Y = boundingSphere.Radius;
                Pivot = tempPos;
            }
            base.Update(deltaTime);
            
            
            boundingSphere.Position = Position;
        }

        public override bool HandleCollision (ref CBaseObject Obj)
        {
           // dont bother checking if we are being held
            if(Held)
            {
                return false;
            }
            CollisionSphere otherSphere = null;
            switch(Obj.Type)
            {
            case ObjectTypes.Nyanimal_Object:
            {
                CNyanimal nyan = (CNyanimal)Obj;
                otherSphere = nyan.BoundingSphere;                                
            } break;
            case ObjectTypes.Player_Object:
            {
                CPlayer player = (CPlayer)Obj;
                otherSphere = player.BoundingSphere;
            } break;
            case ObjectTypes.Food_Object:
            {
                CBaseFood food = (CBaseFood)Obj;
                otherSphere = food.BoundingSphere;
            } break;
            }
            
            if(otherSphere != null)
            {
                // check bounding collition
                Vector3 newPos;
                bool boundingCollision = CMath.SphereToSphere(otherSphere, boundingSphere, out newPos);
                if(boundingCollision == true)
                {
                    newPos.Y = 0.0f; // lock to the plain
                    Position = Position + newPos;
                }
            }
         return false;
            
        }
    }
}

